package elitequant.brokerage;

import java.math.BigDecimal;

import elitequant.data.DataBoard;
import elitequant.event.BacktestEventEngine;
import elitequant.order.FillEvent;
import elitequant.order.OrderEvent;
import elitequant.order.OrderStatus;

/**
 * Backtest brokerage: order placed will be immediately filled.
 * 
 * @author btcaimail@163.com
 *
 */
public class BacktestBrokerage extends BrokerageBase {
	
	private BacktestEventEngine eventsEngine;
	
	private DataBoard dataBoard;
	
	public BacktestBrokerage(BacktestEventEngine eventsEngine, DataBoard dataBoard) {
		this.eventsEngine = eventsEngine;
		this.dataBoard = dataBoard;
	}

	/**
	 * immediate fill, no latency or slippage
	 */
	@Override
	public void placeOrder(OrderEvent orderEvent) {
        // TODO: acknowledge the order
        orderEvent.orderStatus = OrderStatus.FILLED;

        FillEvent fill = new FillEvent();
        fill.internalOrderId = orderEvent.internalOrderId;
        fill.brokerOrderId = orderEvent.brokerOrderId;
        fill.timestamp = dataBoard.getLastTimestamp(orderEvent.fullSymbol);
        fill.fullSymbol = orderEvent.fullSymbol;
        fill.fillSize = orderEvent.size;
        // TODO: use bid/ask to fill short/long
        fill.fillPrice = dataBoard.getLastPrice(orderEvent.fullSymbol);
        fill.exchange = "BACKTEST";
        fill.commission = calculateCommission(fill.fullSymbol, fill.fillPrice, fill.fillSize);

        eventsEngine.put(fill);

	}

	@Override
	public void cancelOrder(String orderId) {

	}

	/**
	 * take ib commission as example
	 * @param fullSymbol
	 * @param fillPrice
	 * @param fillSize
	 * @return
	 */
	@Override
	public BigDecimal calculateCommission(String fullSymbol, BigDecimal fillPrice,
			int fillSize) {
	    BigDecimal commission = BigDecimal.valueOf(0);
        if(fullSymbol.contains("STK")){
            commission = BigDecimal.valueOf(0.005)
                    .multiply(BigDecimal.valueOf(Math.abs(fillSize)))
                    .max(BigDecimal.valueOf(1));
        }
        else if(fullSymbol.contains("FUT")) {
            commission = BigDecimal.valueOf(2.01)
                    .multiply(BigDecimal.valueOf(Math.abs(fillSize)));
        }
        else if(fullSymbol.contains("OPT")) {
            commission = BigDecimal.valueOf(0.7)
                    .multiply(BigDecimal.valueOf(Math.abs(fillSize)))
                    .max(BigDecimal.valueOf(1));
        }
        else if(fullSymbol.contains("CASH")) {
            commission = BigDecimal.valueOf(0.000002)
                    .multiply(fillPrice)
                    .multiply(BigDecimal.valueOf(Math.abs(fillSize)))
                    .max(BigDecimal.valueOf(2));
        }
        return commission;
	}

}
